package com.xiaojie.lock;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * @author xiaojie
 * @version 1.0
 * @description: 基于RedisTemplate实现分布式锁
 * @date 2021/9/19 21:57
 */
@Component
public class RedisTemplateDistributeLock {

    private static final Long SUCCESS = 1L;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * @description: 获取锁
     * @param: lockKey 键值
     * @param: value 唯一的值 区别那个获取到的锁
     * @param: expireTime 过期时间
     * @return: boolean
     * @author xiaojie
     * @date: 2021/9/19 22:15
     */
    public boolean getLock(String lockKey, String value, Long expireTime) {
        try {
            //lua脚本
            String script = "if redis.call('setNx',KEYS[1],ARGV[1]) == 1 then if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end else return 0 end";
            Long result = (Long) redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Collections.singletonList(lockKey), value, expireTime);
            return SUCCESS.equals(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @description: 释放锁
     * @param:
     * @param: lockKey
     * @param: value
     * @return: boolean
     * @author xiaojie
     * @date: 2021/9/19 22:18
     */
    public boolean releaseLock(String lockKey, String value) {
        try {
            //lua脚本
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
            Long result = (Long) redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value);
            redisTemplate.opsForValue().setIfAbsent("a","a",3000, TimeUnit.SECONDS);
            return SUCCESS.equals(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

}
